<template>
	<view class="data-select">
		<view class="stuff" @click="onToggle">
			<slot></slot>
		</view>
		<view v-if="visible" class="mask" @click.stop="onMaskClick"></view>
		<view class="board" :class="{ active: visible, reverse }">
          <view class="selector">
            <view class="arrow"></view>
            <view class="scroller">
            	<view class="term" :class="{ hasBorder, horizontalCenter }" v-for="(term, index) in localdata" :key="term.value" @click="onChange(term, index)">
					<!-- 检查插槽是否被填充 -->
                    <template v-if="$slots['term-content']">
                        <slot name="term-content" :term="term" :index="index"></slot>
                    </template>
                    <template v-else>
                        <!-- 默认内容 -->
                        <view v-if="props.mode === 'radio'" class="radio" :class="{ active: activeState(term, index) }"></view>
                        <text>{{ term.text }}</text>
                    </template>
				</view>
            </view>
          </view>
        </view>
	</view>
</template>

<script setup>
import { ref, watch } from 'vue'
import { useComputed } from '@/utils/useComputed'

const props = defineProps({
	modelValue: {
		type: [String, Number],
		default: ''
	},
	localdata: {
		type: Array,
		default: []
	},
	labelKey: {
		type: String,
		default: 'text'
	},
	valueKey: {
		type: String,
		default: 'value'
	},
	mode: {
		type: String,
		default: 'normal'
	},
	hasBorder: {
		type: Boolean,
		default: false
	},
	horizontalCenter: {
		type: Boolean,
		default: false
	},
	reverse: {
		type: Boolean,
		default: false
	},
	multiple: {
		type: Boolean,
		default: false
	},
	disable: {
		type: Boolean,
		default: false
	}
})
const visible = ref(false)
const activeIndex = ref('')

const emits = defineEmits(['update:modelValue', 'change', 'toggle'])

const activeState = useComputed((term, index) => {
	const { multiple } = props
	if(multiple) {
		return term.active
	} else {
		return activeIndex.value === index
	}
})

const updateInfo = (term, index) => {
	const { mode, valueKey, multiple } = props
	if(multiple) {
		term.active = !term.active
	} else if(mode === 'radio') {
		activeIndex.value = index
	}
	emits('update:modelValue', term[valueKey])
	emits('change', term)
}

watch(() => props.modelValue, (newV) => {
	const { localdata, valueKey } = props
	for (const [index, term] of localdata.entries()) {
		if(term[valueKey] == newV) {
			updateInfo(term, index)
			break
		}
	}
}, { deep: true, immediate: true })

const onToggle = () => {
	if(!props.disable) {
		visible.value = !visible.value
		emits('toggle', visible.value)
	}
}

const onChange = (term, index) => {
	updateInfo(term, index)
	if(!props.multiple) {
		visible.value = false
		emits('toggle', visible.value)
	}
}

const onMaskClick = () => {
	visible.value = false
	emits('toggle', visible.value)
}
</script>

<style lang="scss">
.data-select {
    position: relative;
	.mask {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100vh;
	}
    .board {
        display: none;
        z-index: 2;
        position: absolute;
        top: calc(100% + 24rpx);
        left: 0;
		width: 100%;
        padding: 8rpx 0;
        background-color: #fff;
        border-radius: 12rpx;
        box-shadow: 0 4rpx 24rpx 0 rgba(0, 0, 0, 0.1);
		&.reverse {
			top: unset;
			bottom: calc(100% + 24rpx);
			.selector .arrow {
				top: unset;
				bottom: -20rpx;
				transform: rotate(180deg);
			}
		}
        &.active {
        	display: block;
        }
        .selector {
			position: relative;
			.arrow {
				position: absolute;
				display: block;
				width: 0;
				height: 0;
				border-color: transparent;
				border-style: solid;
				border-width: 6px;
				-webkit-filter: drop-shadow(0 4rpx 24rpx rgba(0, 0, 0, 0.03));
				filter: drop-shadow(0 4rpx 24rpx rgba(0, 0, 0, 0.03));
				top: -18rpx;
				left: 10%;
				margin-right: 6rpx;
				border-top-width: 0;
				border-bottom-color: #fff;
			}
			.scroller {
				max-height: 400rpx;
				overflow-y: scroll;
				.term {
					padding: 0 20rpx;
					display: flex;
					align-items: center;
					height: 70rpx;
					&.hasBorder {
						&:not(:last-child) {
							border-bottom: 1rpx solid #E5E5E5;
						}
					}
					&.horizontalCenter {
						padding: 0;
						justify-content: center;
					}
					.radio {
						position: relative;
						margin-right: 10rpx;
						width: 32rpx;
						height: 32rpx;
						border-radius: 4rpx;
						border: 1rpx solid #999;
						&.active {
							border: none;
							background-color: #0080FF;
							&::before {
								position: absolute;
								top: 25%;
								left: 25%;
								content: '';
								display: block;
								height: 6rpx;
								width: 14rpx;
								border-left: 4rpx solid #fff;
								border-bottom: 4rpx solid #fff;
								transform: rotate(-45deg);
							}
						}
					}
					text {
						font-size: 28rpx;
					}
				}
			}
        }
    }
}
</style>